// Fill out your copyright notice in the Description page of Project Settings.


#include "UserWidget/WidgetComponent/QuestLogWidget.h"
#include "UserWidget/WidgetComponent/SingleQuestCategoryWidget.h"
#include "UserWidget/WidgetComponent/ClickedQuestWidget.h"
#include "UserWidget/WidgetComponent/SingleQuestWidget.h"
#include "UserWidget/WidgetComponent/KeyProgressWidget.h"
#include "Component/MissionComponent.h"
#include "Components/VerticalBox.h"
#include "Components/TextBlock.h"
#include "Components/ScrollBox.h"
#include "Components/SizeBox.h"
#include "Libraries/CommonLibrary.h"
#include "Libraries/MissionSystemFL.h"

void UQuestLogWidget::NativeOnInitialized() {
	Super::NativeOnInitialized();
	DoOnce = true;
}

void UQuestLogWidget::NativeConstruct() {
	Super::NativeConstruct();
	AllCategory=(USingleQuestCategoryWidget*)GetWidgetFromName(TEXT("AllCategory"));
	MainCategory=(USingleQuestCategoryWidget*)GetWidgetFromName(TEXT("MainCategory"));
	SideCategory=(USingleQuestCategoryWidget*)GetWidgetFromName(TEXT("SideCategory"));
	CompletedCategory=(USingleQuestCategoryWidget*)GetWidgetFromName(TEXT("CompletedCategory"));
	Widget_ClickedQuest= (UClickedQuestWidget*)GetWidgetFromName(TEXT("Widget_ClickedQuest"));
	BindClickedWidgetButton();
	CreateQuestList(EQuestCategoryStatus::All);
	UpdateHeadlineText(EQuestCategoryStatus::All,false);
	Widget_ClickedQuest->UpdateClickedQuest(UMissionSystemFL::GetMissionComponent()->CurrentMission);
	USingleQuestCategoryWidget* Temp = Cast<USingleQuestCategoryWidget>(CategoryList->GetChildAt(0));
	Temp->SetSelected();
	BindQuestHover();
	for (int32 i = 0; i < CategoryList->GetAllChildren().Num(); ++i) {
		USingleQuestCategoryWidget* SingleQuest = Cast<USingleQuestCategoryWidget>(CategoryList->GetChildAt(0));
		if (SingleQuest) {
			SingleQuest->QuestCategoryOnClick.AddUFunction(this, "On_Clicked_To_Quest_Category");
			SingleQuest->QuestCategoryOnHovered.AddUFunction(this, "On_Hover_To_Quest_Category");
			SingleQuest->QuestCategoryOnUnHovered.AddUFunction(this, "On_UnHover_Quest_Category");
		}
	}
}

void UQuestLogWidget::ContructWidget(TSubclassOf<USingleQuestWidget> LSingleQuestWidget) {
	SingleQuestWidget = LSingleQuestWidget;
}

void UQuestLogWidget::OnClickedToQuests(USingleQuestWidget* QuestWidget){
	ClickedQuest = QuestWidget;
	UpdateSelectedMission();
	Widget_ClickedQuest->UpdateClickedQuest(ClickedQuest->MissionInfo);
}

void UQuestLogWidget::Stop_Toggle_Track_Timer(){
	if (IsClickedMissionRepeatable() && IsClickedMissionVisible()) {
		Reset_Track_Timer_Handle();
		Widget_ClickedQuest->Widget_KeyProgress->UpdateProgress(0.f,1.f);
	}
}

void UQuestLogWidget::Start_Toggle_Track_Timer(){
	if (IsClickedMissionRepeatable() && IsClickedMissionVisible()) {
		Reset_Track_Timer_Handle();
	}
}

void UQuestLogWidget::On_Track_Completed(bool Filled){
	if (Filled) {
		if (ClickedQuest->IsValidLowLevel()) {
			if (IsTrackedMission(ClickedQuest->MissionInfo)) {
				UMissionSystemFL::GetMissionComponent()->UnTrackMission();
			}
			else {
				UMissionSystemFL::GetMissionComponent()->TrackMission(ClickedQuest->MissionInfo);
			}
			UpdateCurrentMission();
			Widget_ClickedQuest->UpdateClickedQuest(UMissionSystemFL::GetMissionComponent()->CurrentMission);
		}
	}
	else {

	}
}

void UQuestLogWidget::Reset_Track_Timer_Handle(){
	if (DoOnce) {
		DoOnce = false;
		Widget_ClickedQuest->Widget_KeyProgress->UpdateProgress(1.f, 2.f);
	}
}

void UQuestLogWidget::On_Clicked_To_Quest_Category(USingleQuestCategoryWidget* Reference){
	CreateQuestList(Reference->QuestCategory);
}

void UQuestLogWidget::On_Hover_To_Quest_Category(USingleQuestCategoryWidget* SelfReference){
	HoveredWidget = SelfReference;
}
void UQuestLogWidget::On_UnHover_Quest_Category(){
	HoveredWidget = nullptr;
}
void UQuestLogWidget::On_Hover_To_Single_Quest(USingleQuestWidget* SelfReference){
	HoveredWidget = SelfReference;
}
void UQuestLogWidget::On_UnHover_Single_Quest(){
	HoveredWidget = nullptr;
}
void UQuestLogWidget::PopulateQuests(EQuestCategoryStatus Category){
	QuestList->ClearChildren();
	CurrentQuestWidgets.Empty();
	GatherQuests(UMissionSystemFL::GetMissionComponent()->AllMissions);
	switch (Category) {
	case EQuestCategoryStatus::All:
		SetAllQuests();
		AddQuests(AllQuests);
		break;
	case EQuestCategoryStatus::Main:
		AddQuests(MainQuests);
		break;
	case EQuestCategoryStatus::Side:
		AddQuests(SideQuests);
		break;
	case EQuestCategoryStatus::Completed:
		AddQuests(CompletedQuests);
		break;
	default:
		break;
	}
}
void UQuestLogWidget::UpdateHeadline(EQuestCategoryStatus Category){
	const UEnum* EnumPtr = StaticEnum<EQuestCategoryStatus>();
	int32 Index = EnumPtr->GetIndexByValue((int64)Category);
	FText Head = EnumPtr->GetDisplayNameTextByIndex(Index);
	Head.ToUpper();
	ListHeadline->SetText(Head);
}

void UQuestLogWidget::UpdateButtonOpacity(EQuestCategoryStatus Category){
	for (int32 i = 0; i < CategoryList->GetAllChildren().Num(); ++i) {
		USingleQuestCategoryWidget* SingleQuest = Cast<USingleQuestCategoryWidget>(CategoryList->GetChildAt(0));
		if (SingleQuest) {
			SingleQuest->SetUnSelected();
			if (SingleQuest->QuestCategory == Category) {
				SingleQuest->SetSelected();
			}
		}
	}
}

void UQuestLogWidget::CreateQuestList(EQuestCategoryStatus Category){
	PopulateQuests(Category);
	UpdateButtonOpacity(Category);
	UpdateButtonText();
	UpdateCurrentMission();
}

void UQuestLogWidget::SetAllQuests(){
	AllQuests.Empty();
	AllQuests.Append(MainQuests);
	AllQuests.Append(SideQuests);
}

void UQuestLogWidget::GatherQuests(TArray<FMissionMaster> LAllQuests){
	MainQuests.Empty();
	SideQuests.Empty();
	CompletedQuests.Empty();
	for (int32 i = 0; i < LAllQuests.Num(); ++i) {
		switch (LAllQuests[i].MissionCategory) {
		case EQuestCategoryStatus::All:
			break;
		case EQuestCategoryStatus::Main:
			MainQuests.Add(LAllQuests[i]);
			break;
		case EQuestCategoryStatus::Side:
			SideQuests.Add(LAllQuests[i]);
			break;
		case EQuestCategoryStatus::Completed:
			CompletedQuests.Add(LAllQuests[i]);
			break;
		default:
			break;
		}
	}
}
void UQuestLogWidget::AddQuests(TArray<FMissionMaster> LQuestList){
	for (int32 i = 0; i < LQuestList.Num(); ++i) {
		USingleQuestWidget* Temp = Cast<USingleQuestWidget>(CreateWidget(this, SingleQuestWidget));
		if (Temp) {
			Temp->ConstructWidget(LQuestList[i]);
			QuestList->AddChild(Temp);
			Temp->ClickedToQuest.AddUFunction(this, "OnClickedToQuests");
			CurrentQuestWidgets.Add(Temp);
		}
	}
	BindQuestHover();
}

void UQuestLogWidget::UpdateButtonText(){
	TArray<UWidget*> Temp = CategoryList->GetAllChildren();
	for (int32 i = 0; i < Temp.Num(); ++i) {
		USingleQuestCategoryWidget* temp = Cast<USingleQuestCategoryWidget>(Temp[i]);
		int32 Amount = 0;
		switch (temp->QuestCategory) {
		case EQuestCategoryStatus::All:
			Amount = AllQuests.Num();
			break;
		case EQuestCategoryStatus::Main:
			Amount = MainQuests.Num();
			break;
		case EQuestCategoryStatus::Side:
			Amount = SideQuests.Num();
			break;
		case EQuestCategoryStatus::Completed:
			Amount = CompletedQuests.Num();
			break;
		default:
			break;
		}
		temp->UpdateAmount(Amount);
	}
}

void UQuestLogWidget::UpdateCurrentMission(){
	for (int32 i = 0; i < CurrentQuestWidgets.Num(); ++i) {
		CurrentQuestWidgets[i]->SetQuestInActive();
	}
	for (int32 i = 0; i < CurrentQuestWidgets.Num(); ++i) {
		if (IsTrackedMission(CurrentQuestWidgets[i]->MissionInfo)) {
			ClickedQuest = CurrentQuestWidgets[i];
			ClickedQuest->SetQuestActive();
			break;
		}
	}
}

void UQuestLogWidget::UpdateSelectedMission(){
	for (int32 i = 0; i < CurrentQuestWidgets.Num(); ++i) {
		CurrentQuestWidgets[i]->SetUnSelected();
	}
	ClickedQuest->SetSelected();
}

bool UQuestLogWidget::IsTrackedMission(FMissionMaster MissionInfo){
	FText UName = MissionInfo.MissionMainInfo.Name;
	FText UDescription = MissionInfo.MissionMainInfo.Description;
	FText DName = UMissionSystemFL::GetMissionComponent()->CurrentMission.MissionMainInfo.Name;
	FText DDescription = UMissionSystemFL::GetMissionComponent()->CurrentMission.MissionMainInfo.Description;
	return UName.EqualTo(DName) && UDescription.EqualTo(DDescription);
}

void UQuestLogWidget::BindClickedWidgetButton(){
	Widget_ClickedQuest->OnTrackProgressCompleted.Clear();
	Widget_ClickedQuest->OnTrackProgressCompleted.AddUFunction(this, "On_Track_Completed");
}

bool UQuestLogWidget::IsClickedMissionVisible(){
	return Widget_ClickedQuest->ClickedMission->IsVisible();
}
bool UQuestLogWidget::IsClickedMissionRepeatable(){
	bool Result = Widget_ClickedQuest->MissionInfo.MissionCategory == EQuestCategoryStatus::Completed;
	return Result ? Widget_ClickedQuest->MissionInfo.Repeatable : true;
}

void UQuestLogWidget::BindQuestHover(){
	TArray<UWidget*> Temp = QuestList->GetAllChildren();
	for (int32 i = 0; i < Temp.Num(); ++i) {
		USingleQuestWidget* temp = Cast<USingleQuestWidget>(Temp[i]);
		if (temp) {
			temp->HoveredToQuest.AddUFunction(this, "On_Hover_To_Single_Quest");
			temp->UnHoveredQuest.AddUFunction(this, "On_UnHover_Single_Quest");
		}
	}
}

void UQuestLogWidget::ScrollWidget(bool Up){
	TArray<UWidget*> Temp = QuestList->GetAllChildren();
	if (Up) {
		ScrolledIndex = FMath::Clamp(ScrolledIndex + 1, 0, Temp.Num() - 1);
	}
	else {
		ScrolledIndex = FMath::Clamp(ScrolledIndex - 1, 0, Temp.Num() - 1);
	}
	QuestList->ScrollWidgetIntoView(QuestList->GetChildAt(ScrolledIndex), true, EDescendantScrollDestination::TopOrLeft);
}

void UQuestLogWidget::UpdateHeadlineText(EQuestCategoryStatus Category, bool Animate) {
	if (Animate) {
		UWidgetAnimation* Temp=UCommonLibrary::GetAnimInstance(GetClass(), FText::FromString("HeadlineSwitch"));
		PlayAnimation(Temp);
		FTimerDelegate RespawnDelegate = FTimerDelegate::CreateLambda([this, Category]() {
			UpdateHeadline(Category);
			UWidgetAnimation* Temp = UCommonLibrary::GetAnimInstance(GetClass(), FText::FromString("HeadlineSwitch"));
			PlayAnimation(Temp,0.f,1.f,EUMGSequencePlayMode::Reverse);
		});
		FTimerHandle temp;
		GetWorld()->GetTimerManager().SetTimer(temp, RespawnDelegate, Temp->GetEndTime(),false);
	}
	else {
		UpdateHeadline(Category);
	}
}